package com.dekarrin.scraton;

import java.util.ArrayList;
import java.util.HashMap;
import java.io.FileNotFoundException;
import java.io.IOException;

public class SkypeLogParser extends LogParser {

	private static final int DIALOG_TYPE = 60;
	
	private static final int ACTION_TYPE = 61;

	/**
	 * Whether we have read the header line for the CSV file.
	 */
	private boolean haveReadHeader;
	
	/**
	 * The names of the headers.
	 */
	private ArrayList<String> columnNames;
	
	/**
	 * The actual data read from the last line.
	 */
	private ArrayList<String> columnValues;
	
	/**
	 * The last read line from the CSV file mapped to the column names.
	 */
	private HashMap<String, String> lineData;
	
	public SkypeLogParser(String fileName) throws FileNotFoundException {
		super(fileName);
		haveReadHeader = false;
	}

	public ScriptInstruction next() {
		columnValues = null;
		lineData = null;
		ScriptInstruction ins = null;
		if (!haveReadHeader) {
			readHeader();
		}
		readData();
		ins = processData();
		return ins;
	}
	
	private ScriptInstruction processData() {
		if (lineData == null) {
			return null;
		}
		ScriptInstruction in;
		long timestamp = Long.parseLong(lineData.get("timestamp"));
		int type = Integer.parseInt(lineData.get("type"));
		Author author = new Author(lineData.get("from_dispname"), Gender.MALE);
		String content = lineData.get("body_xml");
		switch(type) {
			case DIALOG_TYPE:
			in = new DialogLine(timestamp, author, null, content);
			break;
			
			case ACTION_TYPE:
			default:
			in = new ActionLine(timestamp, author, content);
			break;
		}
		return in;
	}
	
	private void readData() {
		try {
			readLine();	
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (columnValues == null) {
			lineData = null;
		} else {
			lineData = new HashMap<String, String>();
			for (int i = 0; i < columnNames.size(); i++) {
				String k = columnNames.get(i);
				String v = (columnValues.size() > i) ? columnValues.get(i) : "";
				lineData.put(k, v);
			}
		}
	}
	
	private void readHeader() {
		try {
			readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		columnNames = columnValues;
		columnValues = null;
		haveReadHeader = true;
	}
	
	private void readLine() throws IOException {
		columnValues = new ArrayList<String>();
		StringBuilder item = new StringBuilder();
		boolean readingItem = true;
		boolean escaping = false;
		boolean quoted = false;
		int c = -1;
		while ((c = logFileReader.read()) != -1) {
			char n = (char)c;
			if (readingItem) {
				if (item.length() == 0 && n == '"') {
					quoted = true;
					continue;
				}
				if (n == '\\' && !escaping) {
					escaping = true;
					continue;
				}
				if (((n == '"' && quoted) || ((n == ',' || n == '\n') && !quoted)) && !escaping) {
					columnValues.add(item.toString());
					item.delete(0, item.length());
					if (n == '\n') {
						break;
					}
					readingItem = (n == ',');
					quoted = false;
					continue;
				}
				item.append(n);
			} else {
				if (n == '\n') break;
				readingItem = (n == ',');
			}
		}
		if (readingItem) {
			columnValues.add(item.toString());
		}
	}

}